﻿package  
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @author Daniel Sheldon
	 */
	public class Ant extends Sprite
	{
		static private const SEARCHING:uint = 0x00ffff;
		static private const FOUND_FOOD:uint = 0x00ABE4;
		static public const FOOD:uint = 0xff2148A3;
		
		static private const ACTION_SEARCHING:int = 0;
		static private const ACTION_RETURNING_HOME_WITH_FOOD:int = 2;
		static private const ACTION_FOLLOWING:int = 1;
		
		static public var speed:int = 1;
		static public var lifespanMax:int = 500;
		static public var defAlpha:Number = 0.1;
		static public var timer:Timer = new Timer(33);
		static public var ground:PheromoneTrails;
		
		static private const RADIANS:Number = 2 * Math.PI;
		
		private var targetAngle:Number = Math.random() * RADIANS;
		private var angle:Number = targetAngle;
		private var _urge:int = Math.random()*50;
		private var rotationAbility:Number = RADIANS / 20;
		private var lifespan:int = 0;
		private var myLifeSpanMax:int;
		
		private var action:int = ACTION_SEARCHING;
		private var curTrail:uint = SEARCHING;
		
		public var home:Hill;
		
		public function Ant(myLifeSpanMax:int) 
		{
			AntSimulator.numOfAnts++;
			addEventListener(Event.ADDED_TO_STAGE, drawAnt);
			
			var part:int = lifespanMax / 10;
			
			this.myLifeSpanMax = lifespanMax + (Math.random() * part) - (part/ 2);
			cacheAsBitmap = true;
		}
		
		private function drawAnt(e:Event):void 
		{
			var color:uint = 0xffffff;
			
			graphics.beginFill(color);
			graphics.drawRect(-2, -1, 2, 2);
			graphics.endFill();
			
			//graphics.beginFill(0xdedede);
			
			graphics.beginFill(color);
			graphics.drawEllipse(-1, -1, 2, 2) 
			graphics.endFill();
			
			
			this.alpha = defAlpha;
			cacheAsBitmap = true;
			
			startLife();
		}
		
		private function startLife():void
		{
			timer.addEventListener(TimerEvent.TIMER, act);
			if (!timer.running) timer.start();
		}
		
		private function act(e:TimerEvent):void 
		{
			var newX:Number
			var newY:Number 
			
			switch(action)
			{
				case ACTION_RETURNING_HOME_WITH_FOOD:
				{
					newX = x + Math.sin(angle) * speed;
					newY = y + Math.cos(angle) * speed;
					
					x = newX;
					y = newY;
					
					break;
				}
				case ACTION_SEARCHING:
				{
					newX = x + Math.sin(angle) * speed;
					newY = y + Math.cos(angle) * speed;

					rotation = (angle * 57.2957);
					
					if (angle != targetAngle)
					{
						turn();
					}else {
						urge ++;
					}
					
					if (newX < 0 || newX > AntSimulator._width || newY < 0 || newY > AntSimulator._height)
					{
						angle = targetAngle += RADIANS / 2;
						urge = 0
					}else {
						x = newX;
						y = newY;
						
						
						break;
					}
				}
			}
			
			var curColor:uint = ground.bitmapData.getPixel32(x, y);
						
			if (curColor == FOOD)
			{
				angle = findHome()
				action = ACTION_RETURNING_HOME_WITH_FOOD;
				curTrail = FOOD;
			}else{
				var A:uint = curColor >>> 24;
						
				A = Math.min(A + 10, 255);
				
				var colorARBG:uint = (A << 24) + curTrail;
				
				ground.addChange(x, y, colorARBG);
			}
						
			lifespan++;
			
			alpha = defAlpha;
			if (lifespan > myLifeSpanMax)
			{	
				die();
			}
		}
		
		private function findHome():Number
		{
			var distX:Number = x - home.x;
			var distY:Number = y - home.y;
			//var hyp:Number = Math.sqrt((distX * distX) + (distY * distY))
			
			var tan:Number = Math.atan2(distX, distY);
			return tan;
			
		}
		
		private function die():void
		{
			AntSimulator.numOfAnts--;
			timer.removeEventListener(TimerEvent.TIMER, act);
			parent.removeChild(this);
		}
		
		private function turn():void
		{
			var modifier:int = 1;
			
			if (targetAngle > angle)
			{
				modifier = -1;
			}
			
			var distance1:Number = targetAngle - angle;
			var distance2:Number = (targetAngle + (RADIANS * modifier)) - angle;
			var distance:Number;
			
			if (Math.abs(distance1) < Math.abs(distance2))
			{
				distance = distance1;
			}else {
				distance = distance2;
			}
			
			if (distance < 0)
			{
				angle -= rotationAbility;
				if (angle < targetAngle)
					angle = targetAngle;
			}else {
				angle += rotationAbility;
				if (angle > targetAngle)
					angle = targetAngle;
			}
			//angle = targetAngle;
		}
		
		public function get urge():int { return _urge; }
		
		public function set urge(value:int):void 
		{
			_urge = value;
			if (_urge > 50)
			{
				_urge = 0;
				targetAngle = Math.random() * RADIANS;
			}
		}
		
	}
	
}